package main

import (
	"bytes"
	"encoding/binary"
	"github.com/google/gopacket/layers"
	"golang.org/x/net/ipv4"
	"log"
	"net"
	"strconv"
	"syscall"
	"time"
)

func SpoofSendto(destIp string,sourceIp string)  {

	var err error
	destIP := net.ParseIP(destIp)
	srcIP := net.ParseIP(sourceIp)
	proto := 17
	data := []byte("TESTING-ONE-TWO-THREE")

	udpHeader_t := UdpHeader{
		 SourcePort:      8887,
		// DestinationPort: 8888,
		// Length:          uint16(UDP_HEADER_LEN + len(data)),
	}

	buf := bytes.NewBuffer([]byte{})
	err = binary.Write(buf, binary.BigEndian, &udpHeader_t)
	if err != nil {
		log.Fatal(err)
	}

	udpHeader := buf.Bytes()
	dataWithHeader := append(udpHeader, data...)

	h := &ipv4.Header{
		Version:  ipv4.Version,
		Len:      ipv4.HeaderLen,
		TotalLen: ipv4.HeaderLen + UDP_HEADER_LEN + len(data),
		ID:       12345,
		Protocol: proto,
		Dst:      destIP.To4(),
		Src:      srcIP.To4(),
	}

	fd, err := syscall.Socket(syscall.AF_INET, syscall.SOCK_RAW, syscall.IPPROTO_RAW)
	if err != nil {
		log.Fatal(err)
	}

	err = syscall.SetsockoptInt(fd, syscall.IPPROTO_IP, syscall.IP_HDRINCL, 1)
	if err != nil {
		log.Fatal(err)
	}

	addr := syscall.SockaddrInet4{
		Addr: [4]byte{172, 16, 21, 19},
	}

	out, err := h.Marshal()
	if err != nil {
		log.Fatal(err)
	}

	packet := append(out, dataWithHeader...)
	err = syscall.Sendto(fd, packet, 0, &addr)
	if err != nil {
		log.Fatal("Sendto:", err)
	}
	syscall.Close(fd)


}
func main(){
	buf := make([]byte,1024)
	laddr ,_ := net.ResolveUDPAddr("udp4","192.168.2.100:4261")
	lis,e := net.ListenPacket("udp4","127.0.0.1:4261")
	if nil != e{
		log.Print(e.Error())
	}
	go func() {

		for true{
			lis.SetReadDeadline(time.Now().Add(time.Second*10))
			n, addr,e := lis.ReadFrom(buf)
			if nil != e{
				log.Print(e.Error())
			}
			log.Print("recv " + strconv.Itoa(n) + " from: " + addr.String() )
			//laddr ,_ := net.ResolveUDPAddr("udp4","192.168.2.100:122")
			//raddr ,_ :=	net.ResolveUDPAddr("udp4",addr.String())

			p, err := ipv4.NewRawConn(lis)
			if err != nil {
				log.Fatal(err)
			}
			ip := net.ParseIP("127.0.0.1")

			b := []byte("HELLO-R-U-THERE")
			h := &ipv4.Header{
				Version:  ipv4.Version,
				Len:      ipv4.HeaderLen,
				TotalLen: ipv4.HeaderLen + len(b),
				ID:       12345,
				Protocol: 1,
				Dst:      ip.To4(),
			}
			if err := p.WriteTo(h, b, nil); err != nil {
				log.Println(err)
			}
			//cnn.WriteTo([]byte("test"),raddr)
			//raddr ,_ := net.ResolveUDPAddr("udp4","127.0.0.1:134")
			lis.WriteTo([]byte("shit"),addr)
		}
	}()
	laddr ,_ = net.ResolveUDPAddr("udp4","192.168.2.100:1122")
	raddr ,_ := net.ResolveUDPAddr("udp4","192.168.2.100:4261")

	cnn, e := net.DialUDP("udp4",laddr,raddr)
	if nil !=e {
		log.Print(e.Error())
	}

	for true{
		buf := make([]byte,1024)
		cnn.Write([]byte{97,98,99})
		time.Sleep(time.Second)
		n,addr,_  := cnn.ReadFrom(buf)

		log.Print(addr)
		log.Print(buf[0:n])
	}
}